import { Api, ApiResponse as R } from "@/types/http";
import axios, { AxiosRequestConfig, AxiosResponse } from "axios";
import { toLower } from "lodash-es";

type UseAxiosReturn<D, P, M> = {
  loading: Ref<boolean>;
  code: Ref<number>;
  msg: Ref<string>;
  map: M;
  data: Ref<D | undefined>;
  request: (params?: P) => Promise<D>;
};

/**
 * 便捷使用 axios
 * @param api.url 接口地址
 * @param api.method 接口请求方法
 * @param config 配置项
 * @description 泛型 P：请求参数/请求数据类型，
 * @description 泛型 D：响应的数据类型
 * @returns 略
 *
 */
// TODO: 第三个泛型需要改进
export default function useAxios<ParamsType = any, DataType = any, MapType = any>(
  api: Api<MapType>,
  config?: Omit<AxiosRequestConfig, "url" | "method">
): UseAxiosReturn<DataType, ParamsType, MapType> {
  const loading = ref(false);
  const data = ref<DataType>();
  const code = ref<number>(0);
  const msg = ref<string>("");

  const request = async (params?: ParamsType) => {
    const _config = {
      ...api,
      ...config,
    };
    if (["get", "delete"].includes(toLower(api?.method))) {
      _config.params = params;
    } else {
      _config.data = params;
    }

    loading.value = true;
    const res = await axios.request<DataType, AxiosResponse<R<DataType>, ParamsType>>(_config);
    [code.value, data.value, msg.value] = [res.data.code, res.data.data, res.data.message];
    loading.value = false;

    return res.data.data;
  };

  return {
    loading,
    data,
    code,
    msg,
    request,
    map: (() => api.map)(),
  };
}
